use alloc::{string::String, sync::Arc, vec::Vec};
use spin::RwLock;

#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum SchemeTy {
    Dir = 0,
    #[default]
    File = 1,
}

impl From<usize> for SchemeTy {
    fn from(value: usize) -> Self {
        match value {
            0 => SchemeTy::Dir,
            1 => SchemeTy::File,
            _ => panic!("Invalid scheme type"),
        }
    }
}

#[repr(C)]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct FileInfo {
    pub ty: SchemeTy,
    pub name: String,
}

impl FileInfo {
    pub fn new(name: String, ty: SchemeTy) -> Self {
        Self { name, ty }
    }
}

pub trait KernelScheme: Send + Sync + 'static {
    fn when_mounted(&mut self, path: String, father: Option<SchemeRef>);
    fn when_umounted(&mut self);

    fn mount(&mut self, _node: SchemeRef, _name: String) {
        unimplemented!()
    }

    fn get_path(&self) -> String;

    fn size(&self) -> usize {
        0
    }

    fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> usize {
        0
    }
    fn write_at(&self, _offset: usize, _buf: &[u8]) -> usize {
        0
    }
    fn flush(&self) {
        unimplemented!()
    }

    fn open(&self, _name: String) -> Option<SchemeRef> {
        unimplemented!()
    }
    fn create(&self, _name: String, _ty: SchemeTy) -> Option<SchemeRef> {
        unimplemented!()
    }
    fn ioctl(&self, _cmd: usize, _arg: usize) -> usize {
        unimplemented!()
    }
    fn list(&self) -> Vec<FileInfo> {
        Vec::new()
    }

    fn scheme_type(&self) -> SchemeTy {
        SchemeTy::File
    }

    fn stat(&self, buf: &mut [u8]) -> Option<()> {
        None
    }
    fn statvfs(&self, buf: &mut [u8]) -> Option<()> {
        None
    }
}

pub type SchemeRef = Arc<RwLock<dyn KernelScheme>>;
